package main

import (
	"encoding/json"
	"fmt"
)

/*
结构体:由一系列具有相同类型或不同类型的数据构成的数据集合。
*/

// S1 结构体
type S1 struct {
	name  string
	age   int
	hobby []string
}

func main() {
	// 声明一个 S1 类型的变量
	var p S1
	p.name = "xxxx"                   // 通过字段赋值
	p.age = 188                       // 通过字段赋值
	p.hobby = []string{"1", "2", "3"} // 通过字段赋值
	// 访问p的字段
	fmt.Printf("\n结构体变量p的 name 值%s", p.name)
	fmt.Printf("\n结构体变量p的 age 值%d", p.age)

	// 匿名结构体(小写) 多用于一些临时场景
	var s struct {
		x string
		y int
	}
	s.x = "8888"
	s.y = 188
	fmt.Printf("\n匿名结构体变量s%#v", s)
	fmt.Printf("\n匿名结构体变量 s 的 x 值%s", s.x)

	// 结构体占用一块连续的内存空间
	type s2 struct {
		a int8 // 8个bit位 1byte
		b int8
	}
	var b = s2{
		a: 1,
		b: 2,
	}
	fmt.Printf("\nb.a 连续的内存空间 %p", &b.a)
	fmt.Printf("\nb.b 连续的内存空间 %p", &b.b)

	// 结构体嵌套

	type s31 struct {
		Addr string
		Name string
	}
	type s3 struct {
		Id   int
		Name string
		s31

	}
	c := s3{
		Id:   1,
		Name: "xxx",

		//s31: s31{
		//	addr: "cd",
		//	name: "tx",
		//},
	}
	fmt.Printf("\n 结构体嵌套%#v", &c)
	fmt.Printf("\n 结构体嵌套 c.addr 值%#v",c.Addr)
	// 匿名结构体，可以直接拿到最底层的字段， 但可能由于匿名结构体的相同变量，导致字段冲突,所以这里的name是xxx
	fmt.Printf("\n 结构体嵌套 c.name 值%#v",c.Name)

	//结构体比较:结构体是值类型，如果每个字段具有可比性，则是可比较的。如果它们对应的字段相等，则认为两个结构体变量是相等的。

	type D1 struct {
		Age int
		//GG map[string]string   如果结构变量包含的字段是不可比较的，那么结构变量是不可比较的
	}
	var d1 = D1{
		Age: 1,

	}
	var d11= D1{
		Age: 2,
	}

	if d1 ==d11{
		fmt.Print("\n 结构体比较 d1 == d2")
	}else{
		fmt.Print("\n 结构体比较 d1 != d2")
	}

	//结构体指针
	type E struct{
		Age int
	}
	var e1 *E //声明结构体指针变量e1
	fmt.Printf("\n 结构体指针变量 e1 值为%#v",e1)

	// 结构体指针变量实例化-方式一
	e1 = &E{Age: 10}
	// 结构体指针变量实例化-方式二
	var e2 = new(E)
	e2.Age = 20

	// 结构体转 json
	jsonBytes, err := json.Marshal(e1)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("\n 结构体转 json e1 值为%#v",string(jsonBytes))

	// json转结构体
	jsonStr := `
        {
			"age":12
        }
        `
	var e3 E
	err = json.Unmarshal([]byte(jsonStr), &e3)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("\n json转结构体 e2 值为%#v",e3)
/*
以上输出
   结构体变量p的 name 值xxxx
   结构体变量p的 age 值188
   匿名结构体变量sstruct { x string; y int }{x:"8888", y:188}
   匿名结构体变量 s 的 x 值8888
   b.a 连续的内存空间 0xc0000a8088
   b.b 连续的内存空间 0xc0000a8089
    结构体嵌套&main.s3{Id:1, Name:"xxx", s31:main.s31{Addr:"", Name:""}}
    结构体嵌套 c.addr 值""
    结构体嵌套 c.name 值"xxx"
    结构体比较 d1 != d2
    结构体指针变量 e1 值为(*main.E)(nil)
 */
}
